package tolls;

import avenue.MyWindowEvent;
import avenue.Session;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;
import javax.swing.JOptionPane;
import model.DBManager;
import model.Payment;
import model.Vehicle;

public class PaymentForm extends javax.swing.JFrame {

    public PaymentForm() {
        em = DBManager.em;
        if (!em.getTransaction().isActive()){
            em.getTransaction().begin();
        }
        initComponents();
    }
    
    public PaymentForm(Vehicle v) {
        em = DBManager.em;
        vehicle1 = v;
        if ( !em.getTransaction().isActive()){
            em.getTransaction().begin();
        }
        initComponents();
        cardIdTF.setText(vehicle1.getCardId().getId().toString());
        cardIdTF.setEditable(false);
        regNumberTF.setText(vehicle1.getRegNumber());
        regNumberTF.setEditable(false);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        vehicle2 = vehicle1;
        cardIdLabel = new javax.swing.JLabel();
        cardIdTF = new javax.swing.JTextField();
        regNumberLabel = new javax.swing.JLabel();
        regNumberTF = new javax.swing.JTextField();
        payButton = new javax.swing.JButton();
        balanceLabel = new javax.swing.JLabel();
        cardBalanceTF = new javax.swing.JTextField();
        paymentLabel = new javax.swing.JLabel();
        paymentTF = new javax.swing.JTextField();
        newBalanceLabel = new javax.swing.JLabel();
        newBalanceTF = new javax.swing.JTextField();
        cancelButton = new javax.swing.JButton();
        searchButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("Πληρωμή Κάρτας");

        cardIdLabel.setText("Αρ. Κάρτας : ");

        regNumberLabel.setText("Αρ. Πινακίδας : ");

        payButton.setText("Πληρωμή");
        payButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                payButtonActionPerformed(evt);
            }
        });

        balanceLabel.setText("Υπόλοιπο : ");

        cardBalanceTF.setEditable(false);

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, vehicle2, org.jdesktop.beansbinding.ELProperty.create("${cardId.balance}"), cardBalanceTF, org.jdesktop.beansbinding.BeanProperty.create("text"), "balance");
        bindingGroup.addBinding(binding);

        paymentLabel.setText("Ποσό Πληρωμής :  ");

        paymentTF.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                paymentTFCaretUpdate(evt);
            }
        });

        newBalanceLabel.setText("Νέο Υπόλοιπο : ");

        cancelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/cancel.gif"))); // NOI18N
        cancelButton.setText("Ακυρο");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });

        searchButton.setText("Αναζήτηση");
        searchButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                searchButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(payButton)
                    .addComponent(cancelButton)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                        .addComponent(cardIdLabel)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(balanceLabel)
                                        .addGap(14, 14, 14)))
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(cardBalanceTF, javax.swing.GroupLayout.DEFAULT_SIZE, 76, Short.MAX_VALUE)
                                    .addComponent(cardIdTF)))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(paymentLabel)
                                    .addComponent(newBalanceLabel))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(newBalanceTF, javax.swing.GroupLayout.DEFAULT_SIZE, 49, Short.MAX_VALUE)
                                    .addComponent(paymentTF))))
                        .addGap(26, 26, 26)
                        .addComponent(regNumberLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(regNumberTF, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(37, 37, 37)
                        .addComponent(searchButton)))
                .addContainerGap(337, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cardIdLabel)
                    .addComponent(cardIdTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(regNumberLabel)
                    .addComponent(regNumberTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(searchButton))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(balanceLabel)
                    .addComponent(cardBalanceTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(paymentLabel)
                    .addComponent(paymentTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(newBalanceLabel)
                    .addComponent(newBalanceTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(29, 29, 29)
                .addComponent(payButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 62, Short.MAX_VALUE)
                .addComponent(cancelButton)
                .addGap(25, 25, 25))
        );

        bindingGroup.bind();

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed

        // Διαχείριση παραθύρων
        MyWindowEvent we = new MyWindowEvent(this, WindowEvent.WINDOW_CLOSED,false);
        for (WindowListener l : this.getWindowListeners()) {
            l.windowClosed(we);
        }
        this.setVisible(false); 
        
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void paymentTFCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_paymentTFCaretUpdate
        
        try { 
            Double payment = Double.parseDouble(paymentTF.getText());
            if (payment < 0.0) { 
                newBalanceTF.setText("");
            } else { 
                Double newBalance = vehicle1.getCardId().getBalance() + payment;
                newBalanceTF.setText(newBalance.toString());
            }
        } catch(NumberFormatException ex) { 
            newBalanceTF.setText("");
        }
        
    }//GEN-LAST:event_paymentTFCaretUpdate

    private void payButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_payButtonActionPerformed
        
        if (newBalanceTF.getText().equals("")) { 
            JOptionPane.showMessageDialog(this, "Μη έγκυρο νέο υπόλοιπο.",
                                          "Σφάλμα",JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        Double payment = Double.parseDouble(paymentTF.getText());
        Double oldBalance = vehicle1.getCardId().getBalance();
        Double newBalance = oldBalance + payment;
        
        if (payment < 10.0) { 
            JOptionPane.showMessageDialog(this, "Το ποσό πληρωμής δεν μπορεί να είναι κάτω από 10 ευρώ.",
                                          "Σφάλμα",JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        // Δημιουργία ενός αντικειμένου της κλάσης Payment
        Payment p = new Payment();
        em.persist(p);
        // Ανάθεση των πληροφοριών της πληρωμής στο αντικείμενο αυτό
        p.setCardId(vehicle1.getCardId());
        p.setOldBalance(new BigDecimal(oldBalance));
        p.setNewBalance(new BigDecimal(newBalance));
        p.setPaymentTimestamp(new Date());
        p.setStationId(Session.loginUser.getStationId());
        // Ανάθεση του νέου υπολοίπου στην κάρτα
        vehicle1.getCardId().setBalance(newBalance);
        
        // Οριστικοποίηση των αλλαγών;
        em.getTransaction().commit();
        em.getTransaction().begin();
        
        // Διαχείριση παραθύρων
        MyWindowEvent we = new MyWindowEvent(this, WindowEvent.WINDOW_CLOSED,true);
        for (WindowListener l : this.getWindowListeners()) {
            l.windowClosed(we);
        }
        this.setVisible(false); 
        
    }//GEN-LAST:event_payButtonActionPerformed

    private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed

        if (vehicle1 != null)
            return;
        
        // Έλεγχος των δεδομένων εισόδου
        if (regNumberTF.getText().equals("")) {
            JOptionPane.showMessageDialog(this, "Ο αριθμός κυκλοφορίας είναι κενός.",
                                          "Σφάλμα",JOptionPane.ERROR_MESSAGE);
            cardBalanceTF.setText("");
            return;
        } else if (cardIdTF.getText().equals("")) { 
            JOptionPane.showMessageDialog(this, "Ο αριθμός της κάρτας είναι κενός.",
                                          "Σφάλμα",JOptionPane.ERROR_MESSAGE);
            cardBalanceTF.setText("");
            return;
        }
        
        String regNumber = regNumberTF.getText();
        Integer cardId;
        try { 
            cardId = Integer.parseInt(cardIdTF.getText());
        } catch(NumberFormatException ex) { 
            JOptionPane.showMessageDialog(this, "Μη έγκυρος αριθμός κάρτας.",
                                          "Σφάλμα",JOptionPane.ERROR_MESSAGE);
            cardBalanceTF.setText("");
            return;
        }
        
        // Αναζήτησε το όχημα με τον εν λόγω αριθμό πινακίδας και τον εν
        // λόγω αριθμό κάρτας
        Query vehicleQuery = em.createQuery("select v from Vehicle v where "
                + "v.regNumber = :regNumber and v.cardId.id = :cardId");
        
        vehicleQuery.setParameter("regNumber", regNumber);
        vehicleQuery.setParameter("cardId", cardId);
        
        try { 
            // Εκτέλεση της επερώτησης
            vehicle1 = (Vehicle) vehicleQuery.getSingleResult();
            cardBalanceTF.setText(vehicle1.getCardId().getBalance().toString());
        } catch(NoResultException ex) { 
            // Το όχημα δεν βρέθηκε
            JOptionPane.showMessageDialog(this, "Ο συνδυασμός οχήματος/κάρτας δεν βρέθηκε.",
                                          "Σφάλμα",JOptionPane.ERROR_MESSAGE);
            cardBalanceTF.setText("");
            return;
        } catch(NonUniqueResultException ex) { 
            // Βρέθηκαν παραπάνω του ενός αποτελέσματα
            JOptionPane.showMessageDialog(this, "Δεν επιστράφηκε μόνο ένα αποτέλεσμα.",
                                          "Σφάλμα",JOptionPane.ERROR_MESSAGE);
            cardBalanceTF.setText("");
            return;
        }
        
    }//GEN-LAST:event_searchButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel balanceLabel;
    private javax.swing.JButton cancelButton;
    private javax.swing.JTextField cardBalanceTF;
    private javax.swing.JLabel cardIdLabel;
    private javax.swing.JTextField cardIdTF;
    private javax.swing.JLabel newBalanceLabel;
    private javax.swing.JTextField newBalanceTF;
    private javax.swing.JButton payButton;
    private javax.swing.JLabel paymentLabel;
    private javax.swing.JTextField paymentTF;
    private javax.swing.JLabel regNumberLabel;
    private javax.swing.JTextField regNumberTF;
    private javax.swing.JButton searchButton;
    private model.Vehicle vehicle2;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables
    private EntityManager em;
    private Vehicle vehicle1;
    
}
